package org.apache.servicecomb.samples.practise.houserush.login.aggregate;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.fasterxml.jackson.annotation.JsonIgnore;




import lombok.Data;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.persistence.*;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;

/**
 * @Author: Snake Man
 * @system:
 * @DateTime: 2022/1/2 1:30
 * @Description:
 */
@Data
@Entity
@Table(name = "users")
@SQLDelete(sql = "update users set deleted_at = now() where id = ?")
@Where(clause = "deleted_at is null")
@EntityListeners(AuditingEntityListener.class)
public class User {

    private final static String USER_SECRET = "231sdfqwer21313123cafkhioewuqbjffbqwrwr3";
    private final static String HASH_TYPE = "HmacSHA256";

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String username;

    @JsonIgnore//json数据即不包含该属性
    private String hashedPassword;

    @Temporal(TemporalType.TIMESTAMP)
    private Date deletedAt;

    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedAt;

    @Transient//忽略映射
    private String password;
    @Transient
    private String oldPassword;


    @Transient
    private String token;

    //签发token
    public String generateToken(){
        //设置过期时间，240分钟
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MINUTE,240);

        //设置jwt签名算法
        Algorithm algorithm = Algorithm.HMAC256(USER_SECRET);
        //使用jwt生成token

        token = JWT.create()
                .withSubject(String.valueOf(id))//在token里存放用户id
                .withExpiresAt(c.getTime())
                .sign(algorithm);
        return token;
    }


    private static Algorithm algorithm =null;
    //进行token验证的实例
    private static JWTVerifier verifier = null;

    {
        algorithm = Algorithm.HMAC256(USER_SECRET);
        verifier = JWT.require(algorithm).build();
    }

    //进行token鉴权，鉴权成功后，返回用户id
    public static int verifyTokenGetUserId(String token){
        //使用验证者verifier进行验证并获取用户id
        String sbu = verifier.verify(token).getSubject();

        //如果用户id能够正常获取，表示验证成功，返回用户id
        if(StringUtils.isNotEmpty(sbu)){
            return Integer.parseInt(sbu);
        }
        throw   new RuntimeException("令牌token验证失败");
    }


    //密码加密
    public String makeHashedPassword(String password) {
        try {
            String data = username + password;
            SecretKey secretKey = new SecretKeySpec(USER_SECRET.getBytes(), HASH_TYPE);
            Mac mac = Mac.getInstance(HASH_TYPE);
            mac.init(secretKey);
            byte[] bytes = mac.doFinal(data.getBytes());
            return new String(Base64.getEncoder().encode(bytes));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
